gusucode.com > VC++ RingSDK界面库 > VC++ RingSDK界面库/code/libsrc/ringdib/pcx.cpp

    /**********************************************************************
//
//
//        ##########                          ######  #########   # ######    #
//      #############                      ########### ######### #########  ###
//     ######## # ###  ##                 ############# ##    ## #####  # ####
//     ####  ##    ## ###                 ###     ### # #      #####   #####
//          #     ###  #            #     ##       ##  ##      ##     ###
//         ## ###### ##      ##  ####    ####          #       #     ##
//       #########  ###  ## ### #######   ######      ##      ##    ###
//      ######      ##  ######  ##  ##       ####     #      ##     ####
//     #######     ##   ###### ##  ###          ##   ##     ###    ######
//     #########   ##  ###### ## ######         ### ##    ###      #  #####
//    ##    ###### ####### ### #### ##  ## #######  ########      ##    ####
//    ##      #### ###  #  ### ### ##  ##########   ######       ##      ####
//   ##         ##                ##   #########    ####         #         ##
//               #              ###
//                              ##
//                             ###
//                             ##
//
//
//							RingSDK多媒体类库 ringdib.lib
//作者:临风
//
//版本:1.0
//
//声明:本类库可以自由使用而不须对作者作出任何回报,但作者希望能得到
//		  你的鼓励和支持。你可以对类库源码作出修改和改进,但希望你能在
//		  修改的同时给作者一份同样的副本。
//		  本类库不得用于任何商业用途,如确实需要,请与作者联系。
//
//e-mail:ringphone@sina.com
//
//原文件名:pcx.cpp
//
//说明:PCX图象载入功能的实现。(单色及16色图象的解码尚未实现)
//
**********************************************************************/
#define MAKE_SELF_LIB
#include "ringdib.h"

#pragma pack(push,1)
typedef struct tagPCXHEAD
{
	char manufacture;	//always 0x0A
   char version;		//version number
   char encoding;		//should be 1
   char bits_per_pixel;	//color depth
   short xmin,ymin;	//图象左上角坐标
   short xmax,ymax;	//图象宽度=(pcxHead.xmax-pcxHead.xmin)+1;高度同理
   short hres,vres;	//设备分辨率,可忽略
   char palette[48];	//16色下调色板
   char reserved;
   char color_planes;	//颜色面。EGA 16:4,else ,include 单色,=1
   short bytes_per_line;	//扫描线字节数,必须偶数,且!=xmax-xmin
   short palette_type;	//灰度图象为1,全彩:2 Paintbrush后面版本忽略
   short hscreensize;   //为Paintbrush IV/IV+而定义
   short vscreensize;	//其余版本应为NULL
   char filler[54];		//null
}PCXHEAD,*LPPCXHEADER;
#pragma pack(pop)

int xWidth,xHeight;
DWORD dwDataSize;
LPBYTE lpData;
BOOL bOK=FALSE;

int Uncode1(LPBYTE lpData,LPBYTE lpDest,PCXHEAD* ph);
int Uncode16(LPBYTE lpData,LPBYTE lpDest,PCXHEAD* ph);
int Uncode24(LPBYTE lpData,LPBYTE lpDest,PCXHEAD* ph);
int Uncode256(LPBYTE lpData,LPBYTE lpDest,PCXHEAD* ph);

BOOL LoadPCX(LPCTSTR szFilename,RingDIB* lprd,int iFlag,LPSTR lpszFormat)
{
	if(iFlag == DIB_GETFORMAT)
	{
		if(lpszFormat)
		{
			wsprintf(lpszFormat,"pcx");
			return TRUE;
		}
		else
			return FALSE;
	}
   PCXHEAD pcxHead;
   ringFile rf(szFilename);

   rf.Open();
   if(!rf.Read(&pcxHead,sizeof(PCXHEAD)) || pcxHead.manufacture != 0x0A || 
		pcxHead.version < 0x01 || pcxHead.version > 0x05)
      return FALSE;
	else if(iFlag == DIB_QUERYSUPPORT)
		return TRUE;

   xWidth=pcxHead.xmax-pcxHead.xmin+1;
   xHeight=pcxHead.ymax-pcxHead.ymin+1;

   dwDataSize = rf.Size()-sizeof(PCXHEAD);

   lpData=(LPBYTE)New(dwDataSize);
   if(lpData==NULL)
   {
   	//Errmsg("内存分配错误.");
      rf.Close();
      return FALSE;
   }

   if(!rf.Read(lpData,dwDataSize))
   {
      //Errmsg("错误:不能读取文件");
      lpData=(LPBYTE)Del(lpData);
      rf.Close();
      return FALSE;
   }
   rf.Close();
   switch(pcxHead.version)
   {
   	case 0x00:
      	Errmsg("版本太旧,已不支持.");
         lpData=(LPBYTE)Del(lpData);
         return FALSE;
      case 0x02:
      	bOK=Uncode16(lpData,(LPBYTE)lprd->Data(),&pcxHead);
         lpData=(LPBYTE)Del(lpData);
         return bOK;
      case 0x03:
      	bOK=Uncode1(lpData,(LPBYTE)lprd->Data(),&pcxHead);
         lpData=(LPBYTE)Del(lpData);
         return bOK;
      case 0x04:
      case 0x05:
      	if(!lprd->Create(xWidth,xHeight))
         {
         	//Errmsg("内存分配错误.");
		      return FALSE;
         }

      	if(pcxHead.color_planes==3)
         	bOK=Uncode24(lpData,(LPBYTE)lprd->Data(),&pcxHead);
         else if(pcxHead.color_planes==1)
         	bOK=Uncode256(lpData,(LPBYTE)lprd->Data(),&pcxHead);
         lpData=(LPBYTE)Del(lpData);
         return bOK;
      default:
         //Errmsg("版本错误!");
         lpData=(LPBYTE)Del(lpData);
         return FALSE;
   }
}

#if defined  __BORLANDC__
#pragma argsused
#endif
int Uncode1(LPBYTE lpData,LPBYTE lpDest,PCXHEAD* ph)
{
	Errmsg("单色解码尚不支持");
   return TRUE;
}

#if defined  __BORLANDC__
#pragma argsused
#endif
int Uncode16(LPBYTE lpData,LPBYTE lpDest,PCXHEAD* ph)
{
	Errmsg("16色解码尚不支持");
   return TRUE;
}

int Uncode24(LPBYTE lpData,LPBYTE lpDest,PCXHEAD* ph)
{
	DWORD Index,dwScan;//fRes
   int i,j,k,l,count;

   SetCursor(LoadCursor(NULL,IDC_WAIT));

	//////////uncode date//////////
   i=j=k=Index=0;

   dwScan=(xHeight-1)*xWidth*4;
   int len=ph->bytes_per_line*4;

   while(j<xHeight)
   {
      for(l=2;l>=0;l--)
      {
         while(i<len)
         {
            if((lpData[Index]&0xC0)==0xC0)
   		   {
      				count=lpData[Index]&0x3F;
        				Index++;

            	for(k=0;k<count;k++)
	   	     	{
   	   	     	lpDest[dwScan+i+l]=lpData[Index];
      	   	  	i+=4;
	      	     	if(i>=len)
                  {
                  	Index--;
                     lpData[Index]-=(BYTE)(k+1);
                     Index--;
                     break;
                  }
		   	   }
   		   }
	   		else
	      	{
   	      	lpDest[dwScan+i+l]=lpData[Index];
	      	   i+=4;
		      }
            Index++;
            if(Index>=dwDataSize)
            	return FALSE;
         }
         i=0;
      }
      dwScan-=xWidth*4;
      i=0;
      j++;
   }

	return TRUE;
}

int Uncode256(LPBYTE lpData,LPBYTE lpDest,PCXHEAD* ph)
{
   DWORD fSize,Index,dwScan;//fRes
   LPBYTE lpPal;

   int i,j,k,count;

	fSize=dwDataSize;

   if(fSize<769)
   {
   	Errmsg("该文件不是256色图象文件.--无足够调色板信息");
      return FALSE;
   }

   if(lpData[fSize-769]!=0x000C)
   {
   	Errmsg("该文件不是256色图象文件.--错误的调色板信息");
      return FALSE;
   }

   SetCursor(LoadCursor(NULL,IDC_WAIT));

   lpPal=lpData+fSize-768;

   //////////uncode date//////////
   i=j=k=Index=0;
   dwScan=(xHeight-1)*xWidth*4;
   int len=ph->bytes_per_line*4,s;

   while(j<xHeight)
   {
      while(i<len)
      {
	      if((lpData[Index]&0xC0)==0xC0)
  		   {
     			count=lpData[Index]&0x3F;
     			Index++;

            s=lpData[Index]*3+2;
           	for(k=0;k<count;k++)
   	     	{
     	   	  	lpDest[dwScan+i]=lpPal[s];
               i++;s--;
     	   	  	lpDest[dwScan+i]=lpPal[s];
               i++;s--;
     	   	  	lpDest[dwScan+i]=lpPal[s];
               i++;s+=2;
               lpDest[dwScan+i]=0;
               i++;
     	   	  	if(i>=len)
     	   	  		k=count;
	   	   }
  		   }
   		else
      	{
            s=lpData[Index]*3+2;
  	      	lpDest[dwScan+i]=lpPal[s];
            i++;s--;
     	   	lpDest[dwScan+i]=lpPal[s];
            i++;s--;
     	   	lpDest[dwScan+i]=lpPal[s];
            i++;
            lpDest[dwScan+i]=0;
     	   	i++;
	      }
  		   Index++;
         if(Index>=dwDataSize)
           	return FALSE;
      }
      dwScan-=xWidth*4;
      i=0;
      j++;
   }
   return TRUE;
}